package com.econage.eccm.test.base.webdatasource.web;

import com.econage.eccm.test.base.mybatis.uid.IdWorker;
import com.google.common.base.Function;
import com.google.common.util.concurrent.RateLimiter;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.concurrent.TimeUnit;

public class DbTransaction {

    /*
     * 允许自定义密码解密
     */
    public static volatile Function<String,String> PWD_DECRYPT_FUNC;


    private static volatile AppDataSourceContext appDataSourceContext;
    private static final RateLimiter rateLimiter = RateLimiter.create(1,30, TimeUnit.SECONDS);
    static void checkAppDataSource(){
        if(appDataSourceContext==null){
            synchronized (AppDataSourceFilter.class){
                if(appDataSourceContext==null){
                    if(!rateLimiter.tryAcquire()){
                        throw new IllegalStateException("操作过于频繁，请30秒后重试!");
                    }
                    try {
                        appDataSourceContext = new AppDataSourceContext();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    private static AppDataSourceContext getAppDataSourceContext(){
        checkAppDataSource();
        return appDataSourceContext;
    }

    public static Connection fetchConnection(){
        try {
            return getAppDataSourceContext().fetchConnection();
        } catch (SQLException e) {
            throw new IllegalStateException(e);
        }
    }

    static long getDbActionUid(){
        return getAppDataSourceContext().getDbActionUid();
    }

    static long register4Access(){
        if(getAppDataSourceContext().getDbActionUid()!=0){
            throw new IllegalStateException("Cannot register multiple times");
        }
        long actionUid = IdWorker.getId();
        getAppDataSourceContext().register4Access(actionUid);
        return actionUid;
    }

    static void closeForce(long actionUid){
        try {
            getAppDataSourceContext().closeForce(actionUid);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    public static void commit() throws SQLException {
        getAppDataSourceContext().fetchConnection().commit();
    }
    public static void rollback() throws SQLException {
        getAppDataSourceContext().fetchConnection().rollback();
    }

    public static String getDbUrl(){
        return getAppDataSourceContext().getDbUrl();
    }
}
